// r.d(t, { cj: () => DebugTilesRenderer, se: () => l });
import * as THREE from "three"
const n = {}
import TilesRenderer from "./TilesRenderer"
const o = new THREE.Vector3(),
  a = ["x", "y", "z"]
class SphereHelper extends THREE.LineSegments {
  sphere: any
  constructor(e, t = 16776960, r = 40) {
    const n = new THREE.BufferGeometry(),
      i = []
    for (let e = 0; e < 3; e++) {
      const t = a[e],
        s = a[(e + 1) % 3]
      o.set(0, 0, 0)
      for (let e = 0; e < r; e++) {
        let n
        ;(n = (2 * Math.PI * e) / (r - 1)),
          (o[t] = Math.sin(n)),
          (o[s] = Math.cos(n)),
          i.push(o.x, o.y, o.z),
          (n = (2 * Math.PI * (e + 1)) / (r - 1)),
          (o[t] = Math.sin(n)),
          (o[s] = Math.cos(n)),
          i.push(o.x, o.y, o.z)
      }
    }
    n.setAttribute("position", new THREE.BufferAttribute(new Float32Array(i), 3)),
      n.computeBoundingSphere(),
      super(n, new THREE.LineBasicMaterial({ color: t, toneMapped: !1 })),
      (this.sphere = e),
      (this.type = "SphereHelper")
  }
  updateMatrixWorld(e) {
    const t = this.sphere
    this.position.copy(t.center), this.scale.setScalar(t.radius), super.updateMatrixWorld(e)
  }
}
const l = Symbol("ORIGINAL_MATERIAL")
const c = Symbol("HAS_RANDOM_COLOR")
const h = Symbol("HAS_RANDOM_NODE_COLOR")
function u() {}
export default class DebugTilesRenderer extends TilesRenderer {
  static ORIGINAL_MATERIAL: symbol
  displayBoxBounds: boolean
  displaySphereBounds: boolean
  colorMode: number
  customColorCallback: any
  boxGroup: THREE.Group
  sphereGroup: THREE.Group
  maxDebugDepth: number
  maxDebugDistance: number
  maxDebugError: number
  getDebugColor: (e: any, t: any) => void
  extremeDebugDepth: number
  extremeDebugError: number

  constructor(...e) {
    super(...e)
    const t = this.group,
      r = new THREE.Group()
    ;(r.name = "DebugTilesRenderer.boxGroup"), t.add(r)
    const n = new THREE.Group()
    ;(n.name = "DebugTilesRenderer.sphereGroup"),
      t.add(n),
      (this.displayBoxBounds = !1),
      (this.displaySphereBounds = !1),
      (this.colorMode = 0),
      (this.customColorCallback = null),
      (this.boxGroup = r),
      (this.sphereGroup = n),
      (this.maxDebugDepth = -1),
      (this.maxDebugDistance = -1),
      (this.maxDebugError = -1),
      (this.getDebugColor = (e, t) => {
        t.setRGB(e, e, e)
      }),
      (this.extremeDebugDepth = -1),
      (this.extremeDebugError = -1)
  }
  initExtremes() {
    let e = -1
    this.traverse(t => {
      e = Math.max(e, t.__depth)
    })
    let t = -1
    this.traverse(e => {
      t = Math.max(t, e.geometricError)
    }),
      (this.extremeDebugDepth = e),
      (this.extremeDebugError = t)
  }
  fetchTileSet(...e) {
    const t = super.fetchTileSet(...e)
    return (
      t
        .then(() => {
          Promise.resolve().then(() => {
            this.initExtremes()
          })
        })
        .catch(() => {}),
      t
    )
  }
  getTileInformationFromActiveObject(e) {
    let t = null
    return (
      this.activeTiles.forEach((r: any) => {
        if (t) return
        const s = r.cached.scene
        s &&
          s.traverse(s => {
            s === e && (t = r)
          })
      }),
      t
        ? {
            distanceToCamera: t.__distanceFromCamera,
            geometricError: t.geometricError,
            screenSpaceError: t.__error,
            depth: t.__depth,
            isLeaf: t.__isLeaf
          }
        : null
    )
  }
  update() {
    if ((super.update(), !this.root)) return
    ;(this.boxGroup.visible = this.displayBoxBounds), (this.sphereGroup.visible = this.displaySphereBounds)
    let e = -1
    e = -1 === this.maxDebugDepth ? this.extremeDebugDepth : this.maxDebugDepth
    let t = -1
    t = -1 === this.maxDebugError ? this.extremeDebugError : this.maxDebugError
    let r = -1
    r = -1 === this.maxDebugDistance ? this.root.cached.sphere.radius : this.maxDebugDistance
    const n = this.errorTarget,
      i = this.colorMode
    this.visibleTiles.forEach(o => {
      const a = o.cached.scene
      let u, d, p
      7 === i && ((u = Math.random()), (d = 0.5 + 0.5 * Math.random()), (p = 0.375 + 0.25 * Math.random())),
        a.traverse(a => {
          8 === i && ((u = Math.random()), (d = 0.5 + 0.5 * Math.random()), (p = 0.375 + 0.25 * Math.random()))
          const f = a.material
          if (f) {
            const m = a[l]
            if (0 === i && f !== m) a.material.dispose(), (a.material = a[l])
            else if (0 !== i && f === m)
              if (a.isPoints) {
                const e = new THREE.PointsMaterial()
                ;(e.size = m.size), (e.sizeAttenuation = m.sizeAttenuation), (a.material = e)
              } else (a.material = new THREE.MeshStandardMaterial()), (a.material.flatShading = !0)
            switch ((7 !== i && delete a.material[c], 8 !== i && delete a.material[h], i)) {
              case 4: {
                const t = o.__depth / e
                this.getDebugColor(t, a.material.color)
                break
              }
              case 5: {
                const t = o.__depthFromRenderedParent / e
                this.getDebugColor(t, a.material.color)
                break
              }
              case 1: {
                const e = o.__error / n
                e > 1 ? a.material.color.setRGB(1, 0, 0) : this.getDebugColor(e, a.material.color)
                break
              }
              case 2: {
                const e = Math.min(o.geometricError / t, 1)
                this.getDebugColor(e, a.material.color)
                break
              }
              case 3: {
                const e = Math.min(o.__distanceFromCamera / r, 1)
                this.getDebugColor(e, a.material.color)
                break
              }
              case 6:
                o.children && 0 !== o.children.length ? this.getDebugColor(0, a.material.color) : this.getDebugColor(1, a.material.color)
                break
              case 8:
                a.material[h] || (a.material.color.setHSL(u, d, p), (a.material[h] = !0))
                break
              case 7:
                a.material[c] || (a.material.color.setHSL(u, d, p), (a.material[c] = !0))
                break
              case 9:
                this.customColorCallback ? this.customColorCallback(o, a) : console.warn("DebugTilesRenderer: customColorCallback not defined")
            }
          }
        })
    })
  }
  setTileVisible(e, t) {
    super.setTileVisible(e, t)
    const r = e.cached,
      s = this.sphereGroup,
      n = this.boxGroup,
      i = r.boxHelperGroup,
      o = r.sphereHelper
    t ? (i && (n.add(i), i.updateMatrixWorld(!0)), o && (s.add(o), o.updateMatrixWorld(!0))) : (i && n.remove(i), o && s.remove(o))
  }
  parseTile(e, t, r) {
    return super.parseTile(e, t, r).then(() => {
      const e = t.cached,
        r = e.scene
      if (r) {
        if (e.box && e.boxTransform) {
          const r = e.box,
            i = e.boxTransform,
            o = new THREE.Group()
          ;(o.name = "DebugTilesRenderer.boxHelperGroup"), o.matrix.copy(i), (o.matrixAutoUpdate = !1)
          const a = new THREE.Box3Helper(
            r,
            (function (e) {
              if (!n[e]) {
                const t = Math.random(),
                  r = 0.5 + 0.5 * Math.random(),
                  i = 0.375 + 0.25 * Math.random()
                n[e] = new THREE.Color().setHSL(t, r, i)
              }
              return n[e]
            })(t.__depth)
          )
          ;(a.raycast = u),
            o.add(a),
            (e.boxHelperGroup = o),
            this.visibleTiles.has(t) && this.displayBoxBounds && (this.boxGroup.add(o), o.updateMatrixWorld(!0))
        }
        if (e.sphere) {
          const r = e.sphere,
            s = new SphereHelper(r)
          ;(s.raycast = u), (e.sphereHelper = s), this.visibleTiles.has(t) && this.displaySphereBounds && (this.sphereGroup.add(s), s.updateMatrixWorld(!0))
        }
        r.traverse(e => {
          const t = e.material
          t && (e[l] = t)
        })
      }
    })
  }
  disposeTile(e) {
    super.disposeTile(e)
    const t = e.cached
    t.boxHelperGroup && (t.boxHelperGroup.children[0].geometry.dispose(), delete t.boxHelperGroup),
      t.sphereHelper && (t.sphereHelper.geometry.dispose(), delete t.sphereHelper)
  }
}
DebugTilesRenderer.ORIGINAL_MATERIAL = l
